﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.IO;

namespace MuYue.Plugin
{
    /// <summary>
    /// 插件描述
    /// </summary>
    public class PluginContainer
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="pluginXml">插件描述模型</param>
        /// <param name="directory">插件目录</param>
        public PluginContainer(PluginAttribute pluginXml, string directory) {
            this.PluginXml = pluginXml;
            this.directory = directory;
            if (PluginXml.StartPolicy == InitPolicy.Direct)
                LoadPlugin();
        }

        /// <summary>
        /// 插件描述信息
        /// </summary>
        public PluginAttribute PluginXml { set; get; }

        /// <summary>
        /// 插件目录
        /// </summary>
        private string directory;

        #region 反射信息
        /// <summary>
        /// 插件接口类别
        /// </summary>
        public Type PluginInterfaceType { set; get; }

        /// <summary>
        /// 类类别
        /// </summary>
        public Type PluginClassType { set; get; }

        /// <summary>
        /// 标记插件信息是否初始化了
        /// </summary>
        private bool pluginLoaded;
        #endregion

        #region 插件方法
        /// <summary>
        /// 创建插件实例
        /// </summary>
        /// <returns></returns>
        public object CreateInstance(params object[] args) {
            if (!pluginLoaded)
                LoadPlugin();
            return Activator.CreateInstance(PluginClassType, args);
        }

        /// <summary>
        /// 将插件加载到宿主程序中
        /// </summary>
        private void LoadPlugin() {
            if (PluginClassType == null) {
                //将插件正式加载到内存中并且将插件的运行信息处理完成
                var ass = Assembly.LoadFrom(Path.Combine(directory, PluginXml.PluginDllPath));
                //更具插件描述文件提供的插件实现类的名字来提取插件实现类信息
                PluginClassType = ass.GetType(PluginXml.Identify, true);
                //提取插件协议接口信息
                PluginInterfaceType = PluginClassType.GetInterface(PluginXml.PluginInterfaceName);
                //是否在加载插件的时候进行初始化操作
                if (!string.IsNullOrWhiteSpace(PluginXml.Activator)) {
                    var activatorType = ass.GetType(PluginXml.Activator, true);
                    var activator = (IPluginActivator)Activator.CreateInstance(activatorType);
                    activator.Start();
                }
                pluginLoaded = true;
            }
        }
        #endregion
    }
}
